package team.scau.laboratory_repair.common.base;


import com.querydsl.core.support.QueryBase;
import com.querydsl.core.types.dsl.BooleanPath;
import com.querydsl.core.types.dsl.EntityPathBase;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;
import team.scau.laboratory_repair.common.utils.DateTool;
import team.scau.laboratory_repair.common.utils.QDSLTool;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.sql.Timestamp;
import java.util.List;
import java.util.Optional;

/**
 * @author 30254
 * creadtedate:2018/7/25
 */
@CommonsLog
public abstract class BaseService<T extends BaseModel, R extends BaseRepository> {

    public abstract R getRepository();

    public abstract EntityPathBase<T> getQBase();

    @Autowired
    @PersistenceContext
    protected EntityManager entityManager;

    protected JPAQueryFactory queryFactory;

    protected QBaseModel qBaseModel = QBaseModel.baseModel;

    @PostConstruct
    public void init(){
        queryFactory = new JPAQueryFactory(entityManager);
    }

    protected void initEntity(T a){
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        if(a.getId() == null || a.getId() <= 0){
            a.setCreateTime(timestamp);
            a.setValid(true);
        }
        a.setUpdateTime(timestamp);
    }

    public T findById(Object id){
        Optional<T> optional = getRepository().findById(id);
        return optional.orElse(null);
    }

    public List<T> findAll(){
        return queryFactory.select(getQBase()).from(getQBase())
                .where(QDSLTool.getQBeanColumn(getQBase().getClass(), "valid").eq(true)).fetch();
    }

    public Long count() {
        return getRepository().count();
    }

    @Transactional(rollbackFor = Exception.class)
    public void save(T a) throws Exception {
        initEntity(a);
        getRepository().save(a);
    }

    @Transactional(rollbackFor = Exception.class)
    public void delete(T a) throws Exception{
        if(a.getId()==null){
            return;
        }
        a.setDeleteTime(DateTool.getTime());
        a.setValid(false);
        getRepository().save(a);
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveAll(Iterable<T> entities) throws Exception {
        entities.forEach(this::initEntity);
        getRepository().saveAll(entities);
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteById(Object o) throws Exception {
        T t = findById(o);
        delete(t);
    }

}
